#include "mcu_gpio.h"
#include "mcu_top.h"


#define _GPIO_P00_PA0_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P01_PA1_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P02_PA2_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P03_PA3_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P07_PA4_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P09_PA5_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P10_PA6_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P11_PA7_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P14_PA8_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P15_PA9_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P16_PA10_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P17_PA11_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P18_PA12_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P20_PA13_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P23_PA14_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P24_PA15_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P25_PA16_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P26_PA17_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P27_PA18_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P31_PA19_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P32_PA20_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P33_PA21_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿
#define _GPIO_P34_PA22_WUP   0   // wake up polarity select. 0:上升沿，1：下降沿

/**
 * 注意：正常运行状态下必须关闭“输出保留”，仅在休眠前开启！
*/
#define _GPIO_P00_PA0_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P01_PA1_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P02_PA2_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P03_PA3_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P07_PA4_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P09_PA5_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P10_PA6_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P11_PA7_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P14_PA8_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P15_PA9_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P16_PA10_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P17_PA11_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P18_PA12_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P20_PA13_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P23_PA14_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P24_PA15_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P25_PA16_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P26_PA17_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P27_PA18_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P31_PA19_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P32_PA20_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P33_PA21_RET   0   // 休眠/关闭模式下开启输出保留
#define _GPIO_P34_PA22_RET   0   // 休眠/关闭模式下开启输出保留


void GpioIRQHandler();
static void SleepEvent();
static void WeakupEvent();
static void SetRet(bool new_state);

void Gpio_Init()
{
    hal_pwrmgr_unregister(MOD_GPIO);
    hal_pwrmgr_register(MOD_GPIO, SleepEvent, WeakupEvent);

    AP_GPIO->ODR = _GPIO_ODR;
    AP_GPIO->DIR = _GPIO_DIR;
    AP_GPIO->IER = _GPIO_IER;
    AP_GPIO->IMR = ~_GPIO_IER;
    AP_GPIO->INT_MODE = _GPIO_INT_MODE;
    AP_GPIO->INT_POLT = _GPIO_INT_POLT;
    AP_GPIO->ICR = 0XFFFFFFFF;

    //disable all wakeup pin！！！！！！！！！！
    AP_WAKEUP->io_wu_mask_31_0 = 0;     // AP_AON->REG_S9
    AP_WAKEUP->io_wu_mask_34_32 = 0;    // AP_AON->REG_S10


    AP_AON->PMCTL0_f.P31_PA19_PUL = _GPIO_P31_PA19_PUL;
    AP_AON->PMCTL0_f.P31_PA19_WUP = _GPIO_P31_PA19_WUP;
    AP_AON->PMCTL0_f.P32_PA20_PUL = _GPIO_P32_PA20_PUL;
    AP_AON->PMCTL0_f.P32_PA20_RET = _GPIO_P32_PA20_RET;
    AP_AON->PMCTL0_f.P32_PA20_WUP = _GPIO_P32_PA20_WUP;
    AP_AON->PMCTL0_f.P33_PA21_PUL = _GPIO_P33_PA21_PUL;
    AP_AON->PMCTL0_f.P33_PA21_RET = _GPIO_P33_PA21_RET;
    AP_AON->PMCTL0_f.P33_PA21_WUP = _GPIO_P33_PA21_WUP;
    AP_AON->PMCTL0_f.P34_PA22_PUL = _GPIO_P34_PA22_PUL;
    AP_AON->PMCTL0_f.P34_PA22_RET = _GPIO_P34_PA22_RET;
    AP_AON->PMCTL0_f.P34_PA22_WUP = _GPIO_P34_PA22_WUP;
    AP_AON->IOCTL0 = (_GPIO_P00_PA0_WUP << 0)
                    | (_GPIO_P00_PA0_PUL << 1)
                    | (_GPIO_P01_PA1_WUP << 3)
                    | (_GPIO_P01_PA1_PUL << 4)
                    | (_GPIO_P02_PA2_WUP << 6)
                    | (_GPIO_P02_PA2_PUL << 7)
                    | (_GPIO_P03_PA3_WUP << 9)
                    | (_GPIO_P03_PA3_PUL << 10)
                    | (_GPIO_P00_PA0_RET << 13)
                    | (_GPIO_P01_PA1_RET << 14)
                    | (_GPIO_P02_PA2_RET << 16)
                    | (_GPIO_P03_PA3_RET << 17)
                    | (_GPIO_P07_PA4_RET << 19)
                    | (_GPIO_P09_PA5_RET << 20)
                    | (_GPIO_P07_PA4_WUP << 21)
                    | (_GPIO_P07_PA4_PUL << 22)
                    | (_GPIO_P09_PA5_WUP << 27)
                    | (_GPIO_P09_PA5_PUL << 28);
    AP_AON->IOCTL1 = (_GPIO_P10_PA6_WUP << 0)
                    | (_GPIO_P10_PA6_PUL << 1)
                    | (_GPIO_P11_PA7_WUP << 3)
                    | (_GPIO_P11_PA7_PUL << 4)
                    | (_GPIO_P10_PA6_RET << 7)
                    | (_GPIO_P11_PA7_RET << 8)
                    | (_GPIO_P14_PA8_RET << 10)
                    | (_GPIO_P15_PA9_RET << 11)
                    | (_GPIO_P14_PA8_WUP << 12)
                    | (_GPIO_P14_PA8_PUL << 13)
                    | (_GPIO_P15_PA9_WUP << 15)
                    | (_GPIO_P15_PA9_PUL << 16)
                    | (_GPIO_P16_PA10_WUP << 18)
                    | (_GPIO_P16_PA10_PUL << 19)
                    | (_GPIO_P17_PA11_WUP << 21)
                    | (_GPIO_P17_PA11_PUL << 22)
                    | (_GPIO_P18_PA12_WUP << 24)
                    | (_GPIO_P18_PA12_PUL << 25)
                    | (_GPIO_P16_PA10_RET << 28)
                    | (_GPIO_P17_PA11_RET << 29);
    AP_AON->IOCTL2 = (_GPIO_P20_PA13_WUP << 0)
                    | (_GPIO_P20_PA13_PUL << 1)
                    | (_GPIO_P18_PA12_RET << 4)
                    | (_GPIO_P20_PA13_RET << 5)
                    | (_GPIO_P23_PA14_RET << 7)
                    | (_GPIO_P24_PA15_RET << 8)
                    | (_GPIO_P23_PA14_WUP << 9)
                    | (_GPIO_P23_PA14_PUL << 10)
                    | (_GPIO_P24_PA15_WUP << 12)
                    | (_GPIO_P24_PA15_PUL << 13)
                    | (_GPIO_P25_PA16_WUP << 15)
                    | (_GPIO_P25_PA16_PUL << 16)
                    | (_GPIO_P26_PA17_WUP << 18)
                    | (_GPIO_P26_PA17_PUL << 19)
                    | (_GPIO_P27_PA18_WUP << 21)
                    | (_GPIO_P27_PA18_PUL << 22)
                    | (_GPIO_P25_PA16_RET << 25)
                    | (_GPIO_P26_PA17_RET << 26)
                    | (_GPIO_P27_PA18_RET << 28)
                    | (_GPIO_P31_PA19_RET << 29);

    JUMP_FUNCTION(GPIO_IRQ_HANDLER)   =   (uint32_t)&GpioIRQHandler;
    NVIC_SetPriority(GPIO_IRQn, IRQ_PRIO_HAL);
    NVIC_EnableIRQ(GPIO_IRQn);
}

void Gpio_SetDir(gpio_pin_t pin, gpio_dir_t dir)
{
    if(dir)
    {
        AP_GPIO->DIR |= (1 << pin);
    }
    else
    {
        AP_GPIO->DIR &= ~(1 << pin);
    }
}

void Gpio_SetLevel(gpio_pin_t pin, u8 level)
{
    if(level)
    {
        AP_GPIO->ODR |= (1 << pin);
    }
    else
    {
        AP_GPIO->ODR &= ~(1 << pin);
    }
}

u8 Gpio_GetLevel(gpio_pin_t pin)
{
    if(AP_GPIO->IDR & (1 << pin))
    {
        return 1;
    }
    else return 0;
}

void Gpio_SetInt(gpio_pin_t pin, gpio_int_param_t * int_param)
{
    AP_GPIO->IER &= ~(1 << pin);
    AP_GPIO->IER |= (int_param->Enable << pin);
    AP_GPIO->INT_MODE &= ~(1 << pin);
    AP_GPIO->INT_MODE |= (int_param->Mode << pin);
    AP_GPIO->INT_POLT &= ~(1 << pin);
    AP_GPIO->INT_POLT |= (int_param->Polarity << pin);
    AP_GPIO->IMR = ~AP_GPIO->IER;
}

u8 Gpio_GetIntFlag(gpio_pin_t pin)
{
    if(AP_GPIO->INT_FLAG & (1 << pin))
    {
        return 1;
    }
    else return 0;
}

void Gpio_SetPul(gpio_pin_t pin, gpio_pul_t pul)
{
    switch(pin)
    {
        case PA0: AP_AON->IOCTL0_f.P00_PA0_PUL = pul; break;
        case PA1: AP_AON->IOCTL0_f.P01_PA1_PUL = pul; break;
        case PA2: AP_AON->IOCTL0_f.P02_PA2_PUL = pul; break;
        case PA3: AP_AON->IOCTL0_f.P03_PA3_PUL = pul; break;
        case PA4: AP_AON->IOCTL0_f.P07_PA4_PUL = pul; break;
        case PA5: AP_AON->IOCTL0_f.P09_PA5_PUL = pul; break;
        case PA6: AP_AON->IOCTL1_f.P10_PA6_PUL = pul; break;
        case PA7: AP_AON->IOCTL1_f.P11_PA7_PUL = pul; break;
        case PA8: AP_AON->IOCTL1_f.P14_PA8_PUL = pul; break;
        case PA9: AP_AON->IOCTL1_f.P15_PA9_PUL = pul; break;
        case PA10: AP_AON->IOCTL1_f.P16_PA10_PUL = pul; break;
        case PA11: AP_AON->IOCTL1_f.P17_PA11_PUL = pul; break;
        case PA12: AP_AON->IOCTL1_f.P18_PA12_PUL = pul; break;
        case PA13: AP_AON->IOCTL2_f.P20_PA13_PUL = pul; break;
        case PA14: AP_AON->IOCTL2_f.P23_PA14_PUL = pul; break;
        case PA15: AP_AON->IOCTL2_f.P24_PA15_PUL = pul; break;
        case PA16: AP_AON->IOCTL2_f.P25_PA16_PUL = pul; break;
        case PA17: AP_AON->IOCTL2_f.P26_PA17_PUL = pul; break;
        case PA18: AP_AON->IOCTL2_f.P27_PA18_PUL = pul; break;
        case PA19: AP_AON->PMCTL0_f.P31_PA19_PUL = pul; break;
        case PA20: AP_AON->PMCTL0_f.P32_PA20_PUL = pul; break;
        case PA21: AP_AON->PMCTL0_f.P33_PA21_PUL = pul; break;
        case PA22: AP_AON->PMCTL0_f.P34_PA22_PUL = pul; break;
        default: break;
    }
}


/**
 * GPIO中断服务函数（运行在中断中，由MASKROM中的代码调用）
*/
USED WEAK void GpioIRQHandler()
{
    AP_GPIO->ICR = 0XFFFFFFFF;
}

static void SleepEvent()
{
    SetRet(true);// 输出模式IO开启休眠输出保留，注意：正常运行状态下必须关闭“输出保留”，仅在休眠前开启！
    // 输入模式IO获取现在的电平，设置唤醒极性并使能唤醒；保存电平。
}

static void WeakupEvent()
{
    NVIC_SetPriority(GPIO_IRQn, IRQ_PRIO_HAL);
    NVIC_EnableIRQ(GPIO_IRQn);
    // P02 P03设置SWD或者普通IO模式
    // 输出模式IO读写一次ODR，并重新写入DIR设置输出模式
    SetRet(false);// 输出模式IO关闭休眠输出保留
    // 开启中断的IO，设置 边沿触发、使能中断、设置极性
    // 开启中断的IO，判断休眠前的电平与现在的电平是否一致，若不一致手动调用中断回掉。
}

static void SetRet(bool new_state)
{
    if(AP_GPIO->DIR_f.DIR0)AP_AON->IOCTL0_f.P00_PA0_RET = new_state;
    if(AP_GPIO->DIR_f.DIR1)AP_AON->IOCTL0_f.P01_PA1_RET = new_state;
    if(AP_GPIO->DIR_f.DIR2)AP_AON->IOCTL0_f.P02_PA2_RET = new_state;
    if(AP_GPIO->DIR_f.DIR3)AP_AON->IOCTL0_f.P03_PA3_RET = new_state;
    if(AP_GPIO->DIR_f.DIR4)AP_AON->IOCTL0_f.P07_PA4_RET = new_state;
    if(AP_GPIO->DIR_f.DIR5)AP_AON->IOCTL0_f.P09_PA5_RET = new_state;
    if(AP_GPIO->DIR_f.DIR6)AP_AON->IOCTL1_f.P10_PA6_RET = new_state;
    if(AP_GPIO->DIR_f.DIR7)AP_AON->IOCTL1_f.P11_PA7_RET = new_state;
    if(AP_GPIO->DIR_f.DIR8)AP_AON->IOCTL1_f.P14_PA8_RET = new_state;
    if(AP_GPIO->DIR_f.DIR9)AP_AON->IOCTL1_f.P15_PA9_RET = new_state;
    if(AP_GPIO->DIR_f.DIR10)AP_AON->IOCTL1_f.P16_PA10_RET = new_state;
    if(AP_GPIO->DIR_f.DIR11)AP_AON->IOCTL1_f.P17_PA11_RET = new_state;
    if(AP_GPIO->DIR_f.DIR12)AP_AON->IOCTL2_f.P18_PA12_RET = new_state;
    if(AP_GPIO->DIR_f.DIR13)AP_AON->IOCTL2_f.P20_PA13_RET = new_state;
    if(AP_GPIO->DIR_f.DIR14)AP_AON->IOCTL2_f.P23_PA14_RET = new_state;
    if(AP_GPIO->DIR_f.DIR15)AP_AON->IOCTL2_f.P24_PA15_RET = new_state;
    if(AP_GPIO->DIR_f.DIR16)AP_AON->IOCTL2_f.P25_PA16_RET = new_state;
    if(AP_GPIO->DIR_f.DIR17)AP_AON->IOCTL2_f.P26_PA17_RET = new_state;
    if(AP_GPIO->DIR_f.DIR18)AP_AON->IOCTL2_f.P27_PA18_RET = new_state;
    if(AP_GPIO->DIR_f.DIR19)AP_AON->IOCTL2_f.P31_PA19_RET = new_state;
    if(AP_GPIO->DIR_f.DIR20)AP_AON->PMCTL0_f.P32_PA20_RET = new_state;
    if(AP_GPIO->DIR_f.DIR21)AP_AON->PMCTL0_f.P33_PA21_RET = new_state;
    if(AP_GPIO->DIR_f.DIR22)AP_AON->PMCTL0_f.P34_PA22_RET = new_state;
}

